home *** CD-ROM | disk | FTP | other *** search
/ Ham Radio 2000 #1 / Ham Radio 2000.iso / ham2000 / packet / p_aa4re / bb212src / bbdump.pas < prev    next >
Encoding:
Pascal/Delphi Source File  |  1992-03-07  |  38.3 KB  |  1,255 lines

  1. (*===========================================================================*)
  2. (* Procedure for taking system dump                                          *)
  3. (*                                                                           *)
  4. (*   Copyright 1991, 1992 by H. Roy Engehausen.  All rights reserved.        *)
  5. (*                                                                           *)
  6. (*===========================================================================*)
  7.  
  8. {$O+} {This procedure gets overlayed}
  9.  
  10. UNIT BBDUMP;
  11.  
  12. INTERFACE
  13.  
  14. USES
  15.   bbdummy;
  16.  
  17. PROCEDURE dump_init;
  18. PROCEDURE dump_all;
  19. PROCEDURE dump_state;
  20. PROCEDURE dump_overlay;
  21. PROCEDURE dump_trace;
  22. PROCEDURE dump_msg(m_ptr : msg_index_ptr);
  23. PROCEDURE dump_free_list;
  24. PROCEDURE dump_thread(t : tcb_ptr);
  25. PROCEDURE dump_port(p : port_block_ptr);
  26. PROCEDURE dump_all_thread;
  27. PROCEDURE dump_all_msg;
  28. PROCEDURE dump_semaphores;
  29. PROCEDURE dump_window(win_num : BYTE);
  30. PROCEDURE dump_window_all;
  31. PROCEDURE dump_string(s : STRING);
  32. PROCEDURE dump_reason(s : STRING);
  33. PROCEDURE dump_hex(p : POINTER; l : WORD);
  34. PROCEDURE dump_hex_addr(p : POINTER; l : WORD);
  35. PROCEDURE dump_action_item(p : action_msg_ptr);
  36. PROCEDURE dump_action_all;
  37. PROCEDURE dump_search_item(p : search_block_ptr);
  38. PROCEDURE dump_search_chain(p : search_block_ptr);
  39.  
  40. IMPLEMENTATION
  41.  
  42. USES
  43.   CRT,
  44.   DOS,
  45.   bbbug,
  46.   bbmem,
  47.   bbmisc3,
  48.   bbsema2,
  49.   bbtask,
  50.   bbwin;
  51.  
  52. VAR
  53.   dump_file  : TEXT;
  54.   dump_open  : BYTE;
  55.   first_dump : BOOLEAN;
  56.  
  57. (*===========================================================================*)
  58. (* Dump a section of memory                                                  *)
  59. (*===========================================================================*)
  60.  
  61. PROCEDURE hex_dump(p : POINTER; l : WORD);
  62.  
  63.   TYPE
  64.     dump_array = ARRAY[1..4096] OF BYTE;
  65.  
  66.   VAR
  67.     dump_ptr : ^dump_array;
  68.     i        : WORD;
  69.  
  70.   BEGIN;
  71.  
  72.     dump_ptr := p;
  73.  
  74.     FOR i := 1 TO l DO
  75.       BEGIN;
  76.         WRITE(dump_file, b2x(dump_ptr^[i]));
  77.         IF (i AND $1) = 0 THEN
  78.           WRITE(dump_file, ' ');
  79.         IF (i AND $F) = 0 THEN
  80.           WRITELN(dump_file);
  81.       END;
  82.  
  83.     WRITELN(dump_file);
  84.  
  85.   END;
  86.  
  87. (*===========================================================================*)
  88. (* Ready the dump file for output                                            *)
  89. (*===========================================================================*)
  90.  
  91. PROCEDURE dump_init;
  92.  
  93.   VAR
  94.     i : INTEGER;
  95.     j : INTEGER;
  96.     s : STRING[3];
  97.  
  98.   BEGIN;
  99.  
  100.     first_dump := TRUE;
  101.     dump_open  := 0;
  102.  
  103.     FOR i := 1 TO 999 DO
  104.       BEGIN;
  105.         STR(i, s);
  106.         ASSIGN(dump_file, 'DUMP.' + s);
  107.  
  108.         {$I-}
  109.         RESET(dump_file);
  110.         {$I+}
  111.  
  112.         j := IORESULT;
  113.  
  114.         IF j = 2 THEN
  115.           EXIT;
  116.  
  117.         IF j = 0 THEN
  118.           CLOSE(dump_file);
  119.  
  120.       END;
  121.  
  122.     ASSIGN(dump_file, 'DUMP.BB');
  123.  
  124.  
  125.   END;
  126.  
  127. (*===========================================================================*)
  128. (* Ready the dump file for output                                            *)
  129. (*===========================================================================*)
  130.  
  131. PROCEDURE open_dump;
  132.  
  133.   VAR
  134.     i : INTEGER;
  135.  
  136.   BEGIN;
  137.  
  138.     IF first_dump THEN
  139.       BEGIN;
  140.         WRITELN('Dump in progress');
  141.         first_dump := FALSE;
  142.       END;
  143.  
  144.     INC(dump_open);
  145.     IF dump_open > 1 THEN EXIT;
  146.  
  147.     {$I-}
  148.     RESET(dump_file);
  149.     {$I+}
  150.  
  151.     i := IORESULT;
  152.  
  153.     IF i = 0 THEN
  154.       CLOSE(dump_file);
  155.  
  156.     CASE i OF
  157.       0: APPEND(dump_file);
  158.       2: REWRITE(dump_file);
  159.       ELSE
  160.         BEGIN;
  161.           WRITELN('I/O error on dump open');
  162.           HALT;
  163.         END;
  164.  
  165.     END;
  166.  
  167.   END;
  168.  
  169. (*===========================================================================*)
  170. (* Close the dump file                                                       *)
  171. (*===========================================================================*)
  172.  
  173. PROCEDURE close_dump;
  174.   BEGIN;
  175.  
  176.     IF dump_open > 0 THEN
  177.       DEC(dump_open);
  178.  
  179.     IF dump_open > 0 THEN
  180.       EXIT;
  181.  
  182.     CLOSE(dump_file);
  183.  
  184.   END;
  185.  
  186. (*===========================================================================*)
  187. (* Dump a string                                                             *)
  188. (*===========================================================================*)
  189.  
  190. PROCEDURE dump_string(s : STRING);
  191.   BEGIN;
  192.     open_dump;
  193.     WRITELN(dump_file, s);
  194.     close_dump;
  195.   END;
  196.  
  197. (*===========================================================================*)
  198. (* Dump a reason                                                             *)
  199. (*===========================================================================*)
  200.  
  201. PROCEDURE dump_reason(s : STRING);
  202.   BEGIN;
  203.     WRITELN(s);
  204.     open_dump;
  205.     WRITELN(dump_file, s);
  206.     close_dump;
  207.   END;
  208.  
  209. (*===========================================================================*)
  210. (* Dump the call stack                                                       *)
  211. (*===========================================================================*)
  212.  
  213. PROCEDURE dump_call_stack(in_seg : WORD; bp : WORD);
  214.  
  215.   VAR
  216.     called_by     : POINTER;
  217.     depth         : BYTE;
  218.     stack_ptr     : stack_frame_ptr_type;
  219.     displaced_seg : WORD;
  220.  
  221.   BEGIN;
  222.  
  223.     depth := 1;
  224.  
  225.     (*-----------------------------------------------------------------------*)
  226.     (* Loop back thru the stack                                              *)
  227.     (*-----------------------------------------------------------------------*)
  228.  
  229.     stack_ptr.pnt := PTR(in_seg, bp);
  230.  
  231.     REPEAT
  232.  
  233.       (*---------------------------------------------------------------------*)
  234.       (* Get segment we were called from                                     *)
  235.       (*---------------------------------------------------------------------*)
  236.  
  237.       displaced_seg := stack_ptr.pnt^.link_seg;
  238.  
  239.       (*---------------------------------------------------------------------*)
  240.       (* Compute difference from first entry CSEG                            *)
  241.       (*---------------------------------------------------------------------*)
  242.  
  243.       IF displaced_seg >= main_cs THEN
  244.         displaced_seg := displaced_seg - main_cs
  245.       ELSE
  246.         displaced_seg := NOT(main_cs - displaced_seg);
  247.  
  248.       (*---------------------------------------------------------------------*)
  249.       (* Set the result                                                      *)
  250.       (*---------------------------------------------------------------------*)
  251.  
  252.       called_by := PTR(displaced_seg, stack_ptr.pnt^.link_off);
  253.  
  254.       WRITELN(dump_file, 'Proc traceback ', depth, ' = ', p2x(called_by),
  255.                                           ' - ', w2x(stack_ptr.pnt^.link_seg));
  256.  
  257.       INC(depth);
  258.  
  259.       stack_ptr.off := stack_ptr.pnt^.next_bp;
  260.  
  261.     UNTIL (depth > 20)
  262.                 OR (stack_ptr.off = 0)
  263.                 OR (stack_ptr.pnt^.next_bp = 0); (*----- End loop thru stack *)
  264.  
  265.     (*-----------------------------------------------------------------------*)
  266.     (* All done                                                              *)
  267.     (*-----------------------------------------------------------------------*)
  268.  
  269.   END;
  270.  
  271. (*===========================================================================*)
  272. (* Dump everything                                                           *)
  273. (*===========================================================================*)
  274.  
  275. PROCEDURE dump_all;
  276.   BEGIN;
  277.     dump_state;
  278.     dump_overlay;
  279.     dump_trace;
  280.     dump_free_list;
  281.     dump_all_thread;
  282. (*  dump_all_msg; *)
  283.     dump_semaphores;
  284.     dump_window_all;
  285.   END;
  286.  
  287. (*===========================================================================*)
  288. (* Dump operating mode                                                       *)
  289. (*===========================================================================*)
  290.  
  291. TYPE
  292.   op_mode_ptr = ^op_mode;
  293.  
  294. PROCEDURE dump_op_mode(p : op_mode_ptr);
  295.   BEGIN;
  296.     WITH p^ DO
  297.       BEGIN;
  298.         WRITELN(dump_file, 'Fwd emergency only  = ', mode_fwd_emer);
  299.         WRITELN(dump_file, 'No NTS forward      = ', mode_fwd_nonts);
  300.         WRITELN(dump_file, 'Emergency tfc only  = ', mode_acc_emer);
  301.         WRITELN(dump_file, 'No NTS accept       = ', mode_acc_nonts);
  302.         WRITELN(dump_file, 'E mode users only   = ', mode_e_users);
  303.         WRITELN(dump_file, 'Allow call change   = ', mode_user_change);
  304.         WRITELN(dump_file, 'Stop connects       = ', mode_stop_connect);
  305.         WRITELN(dump_file, 'Stop forwarding     = ', mode_stop_fwd);
  306.       END;
  307.   END;
  308.  
  309. (*===========================================================================*)
  310. (* Dump the system state                                                     *)
  311. (*===========================================================================*)
  312.  
  313. PROCEDURE dump_state;
  314.  
  315.   BEGIN;
  316.  
  317.     open_dump;
  318.  
  319.     WRITELN(dump_file);
  320.     WRITELN(dump_file, '==> System state');
  321.     WRITELN(dump_file, 'Main switch         = ', main_switch);
  322.     WRITELN(dump_file, 'Main CS             = ', main_switch);
  323.     WRITELN(dump_file, 'Shutdown switch     = ', shutdown_switch);
  324.     WRITELN(dump_file, 'Dead tcb list       = ', p2x(dead_tcb_list));
  325.     WRITELN(dump_file, 'Active port         = ', p2x(active_port));
  326.     WRITELN(dump_file, 'Active thread       = ', p2x(active_tcb));
  327.     WRITELN(dump_file, 'Forward out busy    = ', fwd_out_busy);
  328.     WRITELN(dump_file, 'Alive tcb count     = ', alive_tcb_count);
  329.     WRITELN(dump_file, 'Overhead tcb count  = ', overhead_tcb_count);
  330.     WRITELN(dump_file, 'Main CS             = ', w2x(main_cs));
  331.     dump_op_mode(@opt_block.operate_mode);
  332.  
  333.     WRITELN(dump_file);
  334.  
  335.     close_dump;
  336.  
  337.   END;
  338.  
  339. (*===========================================================================*)
  340. (* Dump the overlay state                                                    *)
  341. (*===========================================================================*)
  342.  
  343. PROCEDURE dump_overlay_data;
  344.  
  345.   VAR
  346.     over_head       : over_head_type;
  347.     w               : WORD;
  348.  
  349.   BEGIN;
  350.  
  351.     WRITELN(dump_file);
  352.     WRITELN(dump_file, '==> Overlay state');
  353.  
  354.     WRITELN(dump_file, 'Overlay code list   = ', w2x(OvrCodeList));
  355.     WRITELN(dump_file, 'Overlay load list   = ', w2x(OvrLoadList));
  356.     WRITELN(dump_file, 'Overlay size        = ', OvrHeapSize);
  357.     WRITELN(dump_file, 'Overlay debug       = ', p2x(OvrDebugPtr));
  358.     WRITELN(dump_file, 'Overlay start       = ', w2x(OvrHeapOrg));
  359.     WRITELN(dump_file, 'Overlay pointer     = ', w2x(OvrHeapPtr));
  360.     WRITELN(dump_file, 'Overlay end         = ', w2x(OvrHeapEnd));
  361.  
  362.     WRITELN(dump_file);
  363.  
  364.     (*-----------------------------------------------------------------*)
  365.     (* Display the overlay list                                        *)
  366.     (*-----------------------------------------------------------------*)
  367.  
  368.     w := OvrCodeList;
  369.     over_head.off := 0;
  370.  
  371.     WHILE w <> 0 DO
  372.       BEGIN;
  373.         over_head.seg := w + PrefixSeg + $10;
  374.         WITH over_head.pnt^ DO
  375.           BEGIN;
  376.             WRITE(dump_file, 'Overlay ', w2x(w),
  377.                                              ' returns to ', w2x(return_ofs));
  378.             IF load_segment <> 0 THEN
  379.               WRITELN(dump_file, ' -- loaded at ', w2x(load_segment))
  380.             ELSE
  381.               WRITELN(dump_file);
  382.             (* hex_dump(over_head.pnt, 64); *)
  383.             w := code_list_next;
  384.           END;
  385.       END;
  386.  
  387.   END;
  388.  
  389. (*===========================================================================*)
  390. (* Dump the overlay state                                                    *)
  391. (*===========================================================================*)
  392.  
  393. PROCEDURE dump_overlay;
  394.  
  395.   BEGIN;
  396.  
  397.     open_dump;
  398.  
  399.     dump_overlay_data;
  400.  
  401.     close_dump;
  402.  
  403.   END;
  404.  
  405. (*===========================================================================*)
  406. (* Dump the called_by table                                                  *)
  407. (*===========================================================================*)
  408.  
  409. PROCEDURE dump_trace;
  410.  
  411.   VAR
  412.     w : WORD;
  413.  
  414.   BEGIN;
  415.  
  416.     open_dump;
  417.  
  418.     WRITELN(dump_file);
  419.  
  420.     ASM;
  421.       MOV w,BP
  422.     END;
  423.  
  424.     dump_call_stack(SSEG, w);
  425.  
  426.     WRITELN(dump_file);
  427.  
  428.     dump_overlay_data;
  429.  
  430.     close_dump;
  431.  
  432.   END;
  433.  
  434. (*===========================================================================*)
  435. (* Dump a section of memory                                                  *)
  436. (*===========================================================================*)
  437.  
  438. PROCEDURE dump_hex(p : POINTER; l : WORD);
  439.   BEGIN;
  440.  
  441.     open_dump;
  442.  
  443.     WRITELN(dump_file);
  444.  
  445.     hex_dump(p, l);
  446.  
  447.     close_dump;
  448.  
  449.   END;
  450.  
  451. (*===========================================================================*)
  452. (* Dump a section of memory with addresses                                   *)
  453. (*===========================================================================*)
  454.  
  455. PROCEDURE hex_dump_addr(p : POINTER; l : WORD);
  456.  
  457.   TYPE
  458.     dump_array = ARRAY[1..9999] OF BYTE;
  459.  
  460.   VAR
  461.     dump_ptr : ^dump_array;
  462.     i        : WORD;
  463.  
  464.   BEGIN;
  465.  
  466.     dump_ptr := p;
  467.  
  468.     WRITE(dump_file, p2x(dump_ptr), ' ');
  469.  
  470.     FOR i := 1 TO l DO
  471.       BEGIN;
  472.         WRITE(dump_file, b2x(dump_ptr^[i]));
  473.         IF (i AND $1) = 0 THEN
  474.           WRITE(dump_file, ' ');
  475.         IF (i AND $F) = 0 THEN
  476.           BEGIN;
  477.             WRITELN(dump_file);
  478.             IF i <> l THEN
  479.               WRITE(dump_file, p2x(@dump_ptr^[i+1]), ' ');
  480.           END;
  481.       END;
  482.  
  483.     WRITELN(dump_file);
  484.  
  485.   END;
  486.  
  487. (*===========================================================================*)
  488. (* Dump a section of memory                                                  *)
  489. (*===========================================================================*)
  490.  
  491. PROCEDURE dump_hex_addr(p : POINTER; l : WORD);
  492.   BEGIN;
  493.  
  494.     open_dump;
  495.  
  496.     WRITELN(dump_file);
  497.  
  498.     hex_dump_addr(p, l);
  499.  
  500.     close_dump;
  501.  
  502.   END;
  503.  
  504. (*===========================================================================*)
  505. (* Convert a section of memory to a hex string                               *)
  506. (*===========================================================================*)
  507.  
  508. FUNCTION hex_str(p : POINTER; l : BYTE) : STRING;
  509.  
  510.   TYPE
  511.     dump_array = ARRAY[1..256] OF BYTE;
  512.  
  513.   VAR
  514.     dump_ptr : ^dump_array;
  515.     i        : BYTE;
  516.     s        : STRING;
  517.  
  518.   BEGIN;
  519.  
  520.     dump_ptr := p;
  521.     s        := '';
  522.  
  523.     FOR i := 1 TO l DO
  524.       BEGIN;
  525.  
  526.         s := s + b2x(dump_ptr^[i]);
  527.         IF (i AND $3) = 0 THEN
  528.           s := s + ' ';
  529.  
  530.       END;
  531.  
  532.     hex_str := s;
  533.  
  534.   END;
  535.  
  536. (*===========================================================================*)
  537. (* Dump an access block                                                      *)
  538. (*===========================================================================*)
  539.  
  540. PROCEDURE dump_access_block(p: access_block_ptr);
  541.  
  542.   VAR
  543.     x : BYTE;
  544.  
  545.   BEGIN;
  546.  
  547.     x := p^.access_flags;
  548.  
  549.     WRITELN(dump_file, 'Acsblock  = ', b2x(x));
  550.     WRITELN(dump_file, 'Acs sysop = ', (x AND access_f_sysop)     <> 0);
  551.     WRITELN(dump_file, 'Acs bbs   = ', (x AND access_f_bbs)       <> 0);
  552.     WRITELN(dump_file, 'Acs user  = ', (x AND access_f_user)      <> 0);
  553.     WRITELN(dump_file, 'Acs send  = ', (x AND access_f_user_send) <> 0);
  554.  
  555.   END;
  556.  
  557. (*===========================================================================*)
  558. (* Dump a message without changing state of dump file                        *)
  559. (*===========================================================================*)
  560.  
  561. PROCEDURE sub_dump_msg(m_ptr : msg_index_ptr);
  562.  
  563.   VAR
  564.     dis_cnt  : BYTE;
  565.     dis_ptr  : msg_d_ptr;
  566.     i        : BYTE;
  567.     rdis_ptr : msg_dr_ptr;
  568.  
  569.   BEGIN;
  570.  
  571.     WRITELN(dump_file, 'Dump message -- ', m_ptr^.msg_i_mb.msg_number,
  572.                        ' at ', p2x(m_ptr));
  573.  
  574.     WRITELN(dump_file, 'Type      = ', m_ptr^.msg_i_mb.msg_type);
  575.     WRITELN(dump_file, 'Flags     = ', w2x(m_ptr^.msg_i_mb.msg_flag));
  576.     WRITELN(dump_file, 'Size      = ', m_ptr^.msg_i_mb.msg_size);
  577.     WRITELN(dump_file, 'To        = ', m_ptr^.msg_i_mb.msg_to);
  578.     WRITELN(dump_file, 'To @      = ', m_ptr^.msg_i_mb.msg_to_at);
  579.     WRITELN(dump_file, 'Subject   = ', m_ptr^.msg_i_mb.msg_subj);
  580.  
  581.     WRITELN(dump_file);
  582.  
  583.     WRITELN(dump_file, 'Next      = ', p2x(m_ptr^.msg_i_next));
  584.     WRITELN(dump_file, 'Last      = ', p2x(m_ptr^.msg_i_last));
  585.     WRITELN(dump_file, 'Fwd_l     = ', p2x(m_ptr^.msg_i_fwd_l));
  586.     WRITELN(dump_file, 'Other     = ', p2x(m_ptr^.msg_i_dis));
  587.  
  588.     IF m_ptr^.msg_i_dis <> NIL THEN
  589.       WRITELN(dump_file, 'OtherData = ', hex_str(m_ptr^.msg_i_dis, 32));
  590.  
  591.     WRITELN(dump_file);
  592.  
  593.     IF (m_ptr^.msg_i_mb.msg_flag AND mf_fwd_list) <> 0 THEN
  594.       BEGIN;
  595.  
  596.         WRITELN(dump_file, 'Message has distribution list');
  597.         dis_ptr := m_ptr^.msg_i_dis;
  598.  
  599.         IF dis_ptr = NIL THEN
  600.           BEGIN;
  601.             WRITELN(dump_file, 'Distribution list pointer is NIL');
  602.             EXIT;
  603.           END;
  604.  
  605.         IF (m_ptr^.msg_i_mb.msg_flag AND mf_disrout) <> 0 THEN
  606.           BEGIN;
  607.             rdis_ptr := m_ptr^.msg_i_dr;
  608.             dis_ptr  := rdis_ptr^.msg_dr_dblk;
  609.             WRITELN(dump_file, 'Distribution route block indicated -- ',
  610.                                p2x(rdis_ptr));
  611.           END
  612.         ELSE
  613.           rdis_ptr := NIL;
  614.  
  615.         IF dis_ptr = NIL THEN
  616.           BEGIN;
  617.             WRITELN(dump_file,
  618.                      '==> Distribution list pointer from route blocks is NIL');
  619.             EXIT;
  620.           END;
  621.  
  622.         dis_cnt := dis_ptr^.msg_d_no;
  623.  
  624.         WRITELN(dump_file);
  625.         WRITELN(dump_file, 'Distribution count is ', dis_cnt, ' at ',
  626.                             p2x(dis_ptr));
  627.  
  628.         IF dis_cnt > msg_dist_max THEN
  629.           dis_cnt := msg_dist_max;
  630.  
  631.         IF rdis_ptr <> NIL THEN
  632.           BEGIN;
  633.             WRITELN(dump_file);
  634.  
  635.             hex_dump(rdis_ptr, 16);
  636.  
  637.             FOR i := 1 TO dis_cnt DO
  638.               WRITELN(dump_file, 'Rout ', i, ' = ',
  639.                                  p2x(rdis_ptr^.msg_dr_data[i]));
  640.           END;
  641.  
  642.         hex_dump(dis_ptr, 16);
  643.  
  644.         WRITELN(dump_file);
  645.         FOR i := 1 TO dis_cnt DO
  646.           WITH dis_ptr^.msg_d_array[i] DO
  647.             WRITELN(dump_file, 'Distribution ', i, ' = ', w2x(msg_d_flag),
  648.                                                    ' = ', msg_d_info);
  649.  
  650.       END;
  651.  
  652.     WRITELN(dump_file);
  653.  
  654.   END;
  655.  
  656. (*===========================================================================*)
  657. (* Dump a message                                                            *)
  658. (*===========================================================================*)
  659.  
  660. PROCEDURE dump_msg(m_ptr : msg_index_ptr);
  661.   BEGIN;
  662.     open_dump;
  663.     sub_dump_msg(m_ptr);
  664.     close_dump;
  665.   END;
  666.  
  667. (*===========================================================================*)
  668. (* Dump the free chain (Turbo 6)                                            *)
  669. (*===========================================================================*)
  670.  
  671. PROCEDURE dump_free_list;
  672.  
  673.   TYPE
  674.     PFreeRec = ^TFreeRec;
  675.     TFreeRec = RECORD
  676.                  Next : PFreeRec;
  677.                  Size : POINTER;
  678.                END;
  679.  
  680.   VAR
  681.     p1 : PFreeRec;
  682.     p2 : POINTER;
  683.  
  684.   BEGIN;
  685.  
  686.     open_dump;
  687.  
  688.     WRITELN(dump_file, 'HeapOrg   = ', p2x(HeapOrg));
  689.     WRITELN(dump_file, 'HeapPtr   = ', p2x(HeapPtr));
  690.     WRITELN(dump_file, 'FreeList  = ', p2x(FreeList));
  691.     WRITELN(dump_file, 'HeapError = ', p2x(HeapError));
  692.  
  693.     p1 := FreeList;
  694.  
  695.     REPEAT
  696.       BEGIN;
  697.         p2 := PTR(SEG(p1^) + SEG(p1^.Size^),
  698.                   OFS(p1^) + OFS(p1^.Size^));
  699.  
  700.         WRITELN(dump_file, p2x(p1), ' = ', p2x(p1^.Size), ' ',
  701.                            hex_str(p1, 32), ' / ', hex_str(p2, 32));
  702.  
  703.         IF p1 <> HeapPtr THEN
  704.           p1 := p1^.Next;
  705.       END;
  706.     UNTIL p1 = HeapPtr;
  707.  
  708.     WRITELN(dump_file);
  709.  
  710.     close_dump;
  711.  
  712.   END;
  713.  
  714. (*===========================================================================*)
  715. (* Dump all the messages                                                    *)
  716. (*===========================================================================*)
  717.  
  718. PROCEDURE dump_all_msg;
  719.  
  720.   VAR
  721.     p : msg_index_ptr;
  722.  
  723.   BEGIN;
  724.  
  725.     p := msg_index_start;
  726.  
  727.     WHILE p <> NIL DO
  728.       BEGIN;
  729.         dump_msg(p);
  730.         p := p^.msg_i_next;
  731.       END;
  732.  
  733.   END;
  734.  
  735. (*===========================================================================*)
  736. (* Dump a thread                                                            *)
  737. (*===========================================================================*)
  738.  
  739. PROCEDURE sub_dump_thread(t : tcb_ptr; port_too : BOOLEAN);
  740.  
  741.   VAR
  742.     chained_str : str_m_chain;
  743.     chained_mem : mem_list_ptr;
  744.  
  745.   BEGIN;
  746.  
  747.     WRITELN(dump_file);
  748.     WRITELN(dump_file,'==> Dump TCB at ', p2x(t));
  749.     WRITELN(dump_file);
  750.  
  751.     WRITELN(dump_file, 'Next tcb         = ', p2x(t^.next_tcb));
  752.     WRITELN(dump_file, 'Tcb #            = ', t^.tcb_number);
  753.     WRITELN(dump_file, 'Window #         = ', t^.window);
  754.     WRITELN(dump_file, 'Color            = ', t^.w_color);
  755.     WRITELN(dump_file, 'Name             = ', t^.tcb_name);
  756.     WRITELN(dump_file, 'Thread type      = ', ORD(t^.tcb_type));
  757.     WRITELN(dump_file, 'Port             = ', p2x(t^.tcb_port));
  758.     WRITELN(dump_file, 'Channel #        = ', t^.channel);
  759.     WRITELN(dump_file, 'Port/Chan        = ', t^.port_chan_s);
  760.     WRITELN(dump_file, 'Max Pac          = ', t^.max_pac);
  761.  
  762.     WRITELN(dump_file, 'Last L           = ', t^.last_l_time);
  763.  
  764.     WRITELN(dump_file);
  765.  
  766.     WRITELN(dump_file, 'transmit_idle    = ', t^.tcb_transmit_idle   );
  767.     WRITELN(dump_file, 'console          = ', t^.tcb_console         );
  768.     WRITELN(dump_file, 'connect          = ', t^.tcb_connect         );
  769.     WRITELN(dump_file, 'Abbs             = ', t^.tcb_abbs            );
  770.     WRITELN(dump_file, 'Mids_ok          = ', t^.tcb_mids_ok         );
  771.     WRITELN(dump_file, 'H_ok             = ', t^.tcb_h_ok            );
  772.     WRITELN(dump_file, 'Ignore_lc        = ', t^.tcb_ignore_lc       );
  773.     WRITELN(dump_file, 'Opr_talk         = ', t^.tcb_opr_talk        );
  774.     WRITELN(dump_file, 'Ignore_port_chan = ', t^.tcb_ignore_port_chan);
  775.     WRITELN(dump_file, 'Never kill       = ', t^.tcb_never_kill      );
  776.     WRITELN(dump_file, 'Dead_in_progress = ', t^.tcb_dead_in_progress);
  777.     WRITELN(dump_file, 'Dead             = ', t^.tcb_dead            );
  778.     WRITELN(dump_file, 'Stop_tnc_io      = ', t^.tcb_stop_tnc_io     );
  779.     WRITELN(dump_file, 'Make_cc          = ', t^.tcb_make_cc         );
  780.     WRITELN(dump_file, 'No_show_sdata    = ', t^.tcb_no_show_sdata   );
  781.     WRITELN(dump_file, 'Binary           = ', t^.tcb_binary          );
  782.     WRITELN(dump_file, 'Rcv_msg          = ', t^.tcb_rcv_msg         );
  783.     WRITELN(dump_file, 'Rev_fwd          = ', t^.tcb_rev_fwd         );
  784.     WRITELN(dump_file, 'Sysop_pw_ok      = ', t^.tcb_sysop_pw_ok     );
  785.     WRITELN(dump_file, 'Access_ok        = ', t^.tcb_access_ok       );
  786.     WRITELN(dump_file, 'Error_sw         = ', t^.error_sw            );
  787.  
  788.     WRITELN(dump_file, 'Bid Level        = ', t^.tcb_bid_level);
  789.  
  790.     WRITELN(dump_file, 'SS               = ', w2x(t^.sseg_value));
  791.     WRITELN(dump_file, 'SP               = ', w2x(t^.sptr_value));
  792.     WRITELN(dump_file, 'BP               = ', w2x(t^.bptr_value));
  793.     WRITELN(dump_file, 'SS Init          = ', w2x(t^.sseg_init));
  794.     WRITELN(dump_file, 'SS Bot           = ', w2x(t^.sseg_bot));
  795.     WRITELN(dump_file, 'SP Init          = ', w2x(t^.sptr_init));
  796.     WRITELN(dump_file, 'Stack size       = ', t^.sseg_size);
  797.  
  798.     WRITELN(dump_file, 'Stack usage      = ', t^.stack_usage);
  799.     WRITELN(dump_file, 'Stack temp       = ', hex_str(@t^.stack_temp, 10));
  800.     WRITELN(dump_file, 'Stack count      = ', t^.stack_cnt);
  801.  
  802.     WRITELN(dump_file, 'Tnc buffer size  = ', t^.tnc_b_size);
  803.     WRITELN(dump_file, 'Tnc_htt/tth      = ', hex_str(@t^.tnc_htt, 32));
  804.     WRITELN(dump_file, 'Tnc resp type    = ', t^.tnc_type);
  805.     WRITELN(dump_file, 'Tnc data         = ', hex_str(@t^.tnc_data, 32));
  806.     WRITELN(dump_file, 'Tnc null         = ', t^.tnc_null);
  807.  
  808.     WRITELN(dump_file, 'Out line         = ', t^.out_line);
  809.     WRITELN(dump_file, 'Out char         = ', t^.out_char);
  810.  
  811.     WRITELN(dump_file, 'I data           = ', hex_str(@t^.i_data, 32));
  812.     WRITELN(dump_file, 'O data           = ', hex_str(@t^.o_data, 32));
  813.  
  814.     WRITELN(dump_file, 'Fwd msg pointer  = ', hex_str(@t^.curr_fwd, 32));
  815.  
  816.     WRITELN(dump_file, 'Conv tcb         = ', p2x(t^.conv_tcb));
  817.  
  818.     dump_access_block(@t^.tcb_access_mode);
  819.  
  820.     WRITELN(dump_file);
  821.  
  822.     WRITELN(dump_file, 'Uid data');
  823.     hex_dump(@t^.uid_data, 128);
  824.  
  825.     WRITELN(dump_file);
  826.  
  827.     chained_str := t^.tnc_in_chn;
  828.     WRITELN(dump_file, 'Input chain      = ', p2x(chained_str));
  829.  
  830.     WHILE chained_str <> NIL DO
  831.       BEGIN;
  832.         hex_dump_addr(chained_str, 32);
  833.         chained_str := chained_str^.str_m_next;
  834.       END;
  835.  
  836.     WRITELN(dump_file);
  837.  
  838.     chained_str := t^.tnc_in_chn;
  839.     WRITELN(dump_file, 'C input          = ', p2x(chained_str));
  840.  
  841.     WHILE chained_str <> NIL DO
  842.       BEGIN;
  843.         hex_dump_addr(chained_str, 32);
  844.         chained_str := chained_str^.str_m_next;
  845.       END;
  846.  
  847.     WRITELN(dump_file);
  848.     chained_mem := t^.stor_list;
  849.     WRITELN(dump_file, 'Storage list     = ', p2x(chained_mem));
  850.  
  851.     WHILE chained_mem <> NIL DO
  852.       BEGIN;
  853.         hex_dump_addr(chained_mem, 32);
  854.         chained_mem := chained_mem^.next_mem_list;
  855.       END;
  856.  
  857.     WRITELN(dump_file);
  858.     sub_dump_msg(@t^.curr_msg);
  859.  
  860.     IF t <> active_tcb THEN
  861.       BEGIN;
  862.         WRITELN(dump_file);
  863.         dump_call_stack(t^.sseg_value, t^.bptr_value);
  864.       END;
  865.  
  866.   END;
  867.  
  868. (*===========================================================================*)
  869. (* Dump a thread                                                            *)
  870. (*===========================================================================*)
  871.  
  872. PROCEDURE dump_thread(t : tcb_ptr);
  873.   BEGIN;
  874.     open_dump;
  875.     sub_dump_thread(t, FALSE);
  876.     close_dump;
  877.   END;
  878.  
  879. (*===========================================================================*)
  880. (* Dump a port                                                              *)
  881. (*===========================================================================*)
  882.  
  883. PROCEDURE dump_port_data(p : port_block_ptr);
  884.   BEGIN;
  885.  
  886.     WRITELN(dump_file);
  887.     WRITELN(dump_file,'==> Dump port at ', p2x(p));
  888.     WRITELN(dump_file);
  889.  
  890.     WRITELN(dump_file, 'Next port        = ', p2x(p^.next_port));
  891.     WRITELN(dump_file, 'Main port        = ', p2x(p^.main_port));
  892.     WRITELN(dump_file, 'Aux thread       = ', p2x(p^.aux_thread));
  893.     WRITELN(dump_file, 'Com #            = ', p^.com_number);
  894.     WRITELN(dump_file, 'Port Char        = ', p^.port_char);
  895.     WRITELN(dump_file, 'Port Name        = ', p^.port_name);
  896.     WRITELN(dump_file, 'Port Type        = ', ORD(p^.port_type));
  897.     WRITELN(dump_file, 'Host Only TNC    = ', p^.port_host_only);
  898.     WRITELN(dump_file, 'Sub Port         = ', p^.port_sub_port);
  899.     WRITELN(dump_file, 'Monitor          = ', p^.port_monitor);
  900.     WRITELN(dump_file, 'Remote Sysop OK? = ', p^.port_r_sysop);
  901.     WRITELN(dump_file, 'Broadcast        = ', p^.port_bcst);
  902.     WRITELN(dump_file, 'Up/Download OK?  = ', p^.port_up_down);
  903.     WRITELN(dump_file, 'Binary Xfr OK?   = ', p^.port_no_binary);
  904.     WRITELN(dump_file, 'PK232 Ack needed = ', p^.port_pk232_data_ack);
  905.     WRITELN(dump_file, 'No outbound fwd  = ', p^.port_no_out_fwd);
  906.     WRITELN(dump_file, 'No fwd when busy = ', p^.port_no_busy_fwd);
  907.     WRITELN(dump_file, 'SSID supress     = ', p^.port_suppress_ssid);
  908.     WRITELN(dump_file, 'Use user chan fwd= ', p^.port_use_user_chan);
  909.     WRITELN(dump_file, 'Dflt transparent = ', p^.port_dflt_trans);
  910.     WRITELN(dump_file, 'PCPA Port number = ', p^.port_num);
  911.     WRITELN(dump_file, 'Color            = ', p^.port_color);
  912.     WRITELN(dump_file, 'Semaphore        = ', p^.port_sema);
  913.     WRITELN(dump_file, 'No mail bcst     = ', p^.port_no_mail_bcst);
  914.     WRITELN(dump_file, 'No mail count    = ', p^.port_no_mail_cnt);
  915.     WRITELN(dump_file, 'User class allow = ', ORD(p^.port_allow));
  916.     WRITELN(dump_file, 'Default pkt size = ', p^.dflt_pac);
  917.     WRITELN(dump_file, 'Maximum pkt size = ', p^.max_pac);
  918.     WRITELN(dump_file, 'Data rate        = ', p^.data_rate);
  919.     WRITELN(dump_file, 'Time out         = ', p^.data_rate);
  920.     WRITELN(dump_file, 'Forward minute   = ', p^.fwd_min);
  921.     WRITELN(dump_file, 'Maximum connect  = ', p^.max_conn);
  922.     WRITELN(dump_file, 'Maximum channels = ', p^.max_chan);
  923.     WRITELN(dump_file, 'Maximum pkt pend = ', p^.port_pend);
  924.     WRITELN(dump_file, 'Dflt screen len  = ', p^.dflt_scrl);
  925.     WRITELN(dump_file, 'Dflt display fmt = ', p^.new_display);
  926.     WRITELN(dump_file, 'Reject action    = ', p^.reject_act);
  927.     WRITELN(dump_file, 'Dflt language    = ', p^.dflt_lang);
  928.     WRITELN(dump_file, 'First load name  = ', p^.first_load);
  929.     WRITELN(dump_file, 'Dflt ordering    = ', p^.dflt_order);
  930.  
  931.     dump_op_mode(@p^.port_operate_mode);
  932.  
  933.     dump_access_block(@p^.dflt_access);
  934.  
  935.     IF p^.port_type <> port_modem THEN
  936.       BEGIN;
  937.       END
  938.     ELSE
  939.       BEGIN;
  940.         WRITELN(dump_file, 'Modem options    = ', p^.modem_optns);
  941.         WRITELN(dump_file, 'Answer on ring   = ', p^.answer_ring);
  942.         WRITELN(dump_file, 'CR timeout       = ', p^.cr_timeout);
  943.         WRITELN(dump_file, 'Current rate     = ', p^.cur_rate);
  944.         WRITELN(dump_file, 'Echo             = ', p^.modem_echo);
  945.         WRITELN(dump_file, 'Echo now         = ', p^.modem_e_now);
  946.         WRITELN(dump_file, 'CR=CR/LF         = ', p^.modem_crlf);
  947.         WRITELN(dump_file, 'Dialing          = ', p^.modem_dial);
  948.         WRITELN(dump_file, 'Connect message  = ', p^.modem_conn);
  949.         WRITELN(dump_file, 'Freeze speed?    = ', p^.modem_freez);
  950.         WRITELN(dump_file, 'Modem DCD        = ', p^.port_modem_dcd);
  951.       END;
  952.   END;
  953.  
  954. (*===========================================================================*)
  955. (* Dump a port                                                              *)
  956. (*===========================================================================*)
  957.  
  958. PROCEDURE dump_port(p : port_block_ptr);
  959.   BEGIN;
  960.     open_dump;
  961.     dump_port_data(p);
  962.     close_dump;
  963.   END;
  964.  
  965. (*===========================================================================*)
  966. (* Dump all threads and ports                                               *)
  967. (*===========================================================================*)
  968.  
  969. PROCEDURE dump_all_thread;
  970.  
  971.   VAR
  972.  
  973.     p : port_block_ptr;
  974.     t : tcb_ptr;
  975.  
  976.   BEGIN;
  977.  
  978.     open_dump;
  979.  
  980.     dump_state;
  981.  
  982.     t := ring_tcb;
  983.     REPEAT
  984.       sub_dump_thread(t, FALSE);
  985.       t := t^.next_tcb;
  986.     UNTIL t = ring_tcb;
  987.  
  988.     p := ring_port;
  989.     REPEAT
  990.       dump_port_data(p);
  991.       p := p^.next_port;
  992.     UNTIL p = ring_port;
  993.  
  994.     dump_port_data(@dummy_port);
  995.  
  996.     close_dump;
  997.  
  998.   END;
  999.  
  1000. (*===========================================================================*)
  1001. (* Dump Semaphores                                                          *)
  1002. (*===========================================================================*)
  1003.  
  1004. PROCEDURE dump_semaphores;
  1005.  
  1006.   VAR
  1007.  
  1008.     i          : INTEGER;
  1009.     sem_num    : BYTE;
  1010.     w_proc_l   : sem_process_ptr;
  1011.     w_tcb      : tcb_ptr;
  1012.  
  1013.   BEGIN;
  1014.  
  1015.     open_dump;
  1016.  
  1017.     FOR sem_num := 1 TO high_semaphore DO
  1018.       BEGIN;
  1019.  
  1020.         WRITELN(dump_file, 'Semaphore # ', sem_num);
  1021.  
  1022.         WITH sem_info_array[sem_num] DO
  1023.           BEGIN;
  1024.  
  1025.             CASE sem_status OF
  1026.               sem_clear     : WRITELN(dump_file, 'Semaphore is clear');
  1027.               sem_shared    : WRITELN(dump_file, 'Semaphore is shared');
  1028.               sem_exclusive : WRITELN(dump_file, 'Semaphore is exclusive');
  1029.             END;
  1030.  
  1031.             WRITELN(dump_file, 'Timeout is ',
  1032.                                         time_out, ' -- Xcount = ', excl_count);
  1033.             WRITELN(dump_file, 'Last unlock was ', p2x(last_unlock));
  1034.  
  1035.             w_proc_l := process_list;
  1036.             WHILE w_proc_l <> NIL DO
  1037.               BEGIN;
  1038.                 WITH w_proc_l^.process_tcb^ DO
  1039.                   BEGIN;
  1040.                     IF task_is_dead(w_proc_l^.process_tcb) THEN
  1041.                       WRITELN(dump_file,
  1042.                               ' TCB # ', tcb_number,
  1043.                               ' Dead status -- ', port_chan_s)
  1044.                     ELSE
  1045.                       WRITELN(dump_file,
  1046.                               ' TCB # ', tcb_number, ' - ', tcb_name,
  1047.                               ' - ', port_chan_s);
  1048.                     WRITELN(dump_file,
  1049.                             ' Locked by ', p2x(w_proc_l^.process_who));
  1050.  
  1051.                   END;
  1052.                 w_proc_l := w_proc_l^.next_process;
  1053.               END;
  1054.  
  1055.           END;
  1056.  
  1057.       END;
  1058.  
  1059.     close_dump;
  1060.  
  1061.   END;
  1062.  
  1063. (*===========================================================================*)
  1064. (* Dump a window                                                             *)
  1065. (*===========================================================================*)
  1066.  
  1067. PROCEDURE dump_window(win_num : BYTE);
  1068.  
  1069.   VAR
  1070.     i : WORD;
  1071.     p : POINTER;
  1072.     l : window_data_ptr;
  1073.     w : window_data_ptr;
  1074.  
  1075.   BEGIN;
  1076.  
  1077.     open_dump;
  1078.  
  1079.     WRITELN(dump_file);
  1080.     WRITELN(dump_file, 'Window #', win_num);
  1081.  
  1082.     WITH window_array[win_num] DO
  1083.       BEGIN;
  1084.  
  1085.         WRITELN(dump_file, 'Window active?    = ', window_act);
  1086.         WRITELN(dump_file, 'Window cursor     = ', window_cursor);
  1087.         WRITELN(dump_file, 'Window location   = ', window_loc);
  1088.         WRITELN(dump_file, 'Window scrolling  = ', window_scrollable);
  1089.         WRITELN(dump_file, 'Window at top?    = ', window_at_top);
  1090.         WRITELN(dump_file, 'Window max data   = ', window_max_data);
  1091.         WRITELN(dump_file, 'Window count      = ', window_count);
  1092.         WRITELN(dump_file, 'Window data       = ', p2x(window_data));
  1093.         WRITELN(dump_file, 'Window line       = ', p2x(window_line));
  1094.         WRITELN(dump_file, 'Window last       = ', p2x(window_last));
  1095.  
  1096.         WRITELN(dump_file);
  1097.  
  1098.         i := 500;
  1099.  
  1100.         w := window_line;
  1101.         l := window_line^.last_line;
  1102.         WHILE (w <> NIL) AND (w <> l) AND (i > 0) DO
  1103.           BEGIN;
  1104.  
  1105.             WRITELN(dump_file, p2x(w), '=', p2x(w^.next_line), '/',
  1106.                                             p2x(w^.last_line), ' ',
  1107.                                             w^.line_color);
  1108.  
  1109.             WRITELN(dump_file, LENGTH(w^.this_line), '-', w^.this_line);
  1110.  
  1111.       (* Only use this for overlay write into window area *)
  1112.       (*    p := w;
  1113.             p := PTR(SEG(p^) - 17, OFS(p^));
  1114.             hex_dump_addr(p, 320);  *)
  1115.  
  1116.             w := l;
  1117.             l := w^.last_line;
  1118.  
  1119.             DEC(i);
  1120.  
  1121.           END;
  1122.  
  1123.         WRITELN(dump_file, 'Window ends -- ', p2x(w), ' -- ', p2x(l),
  1124.                                                       ' -- ', i);
  1125.  
  1126.       END;
  1127.  
  1128.     close_dump;
  1129.  
  1130.   END;
  1131.  
  1132. (*===========================================================================*)
  1133. (* Dump all windows                                                          *)
  1134. (*===========================================================================*)
  1135.  
  1136. PROCEDURE dump_window_all;
  1137.  
  1138.   VAR
  1139.     i : BYTE;
  1140.  
  1141.   BEGIN;
  1142.  
  1143.     FOR i := 0 TO window_max DO
  1144.       dump_window(i);
  1145.  
  1146.   END;
  1147.  
  1148. (*===========================================================================*)
  1149. (* Dump an action item                                                       *)
  1150. (*===========================================================================*)
  1151.  
  1152. PROCEDURE dump_action_item(p : action_msg_ptr);
  1153.   BEGIN;
  1154.  
  1155.     WRITELN(dump_file, 'Dumping action item at -- ', p2x(p));
  1156.     WRITELN(dump_file);
  1157.  
  1158.     WRITELN(dump_file, 'Next action = ', p2x(p^.next_action));
  1159.     WRITELN(dump_file, 'Action type = ', b2x(p^.action_type));
  1160.     dump_search_chain(p^.action_srch);
  1161.     WRITELN(dump_file, 'Action data = ');
  1162.     hex_dump_addr(@p^.action_info, 64);
  1163.  
  1164.   END;
  1165.  
  1166. (*===========================================================================*)
  1167. (* Dump all action items                                                     *)
  1168. (*===========================================================================*)
  1169.  
  1170. PROCEDURE dump_action_all;
  1171.  
  1172.   VAR
  1173.     p : action_msg_ptr;
  1174.     loop_count : BYTE;
  1175.  
  1176.   BEGIN;
  1177.  
  1178.     open_dump;
  1179.     loop_count := 10;
  1180.  
  1181.     p := first_msg_action;
  1182.  
  1183.     WRITELN(dump_file, 'Dumping action chain starting at -- ', p2x(p));
  1184.     WRITELN(dump_file);
  1185.  
  1186.     WHILE (p <> NIL) AND (loop_count > 0) DO
  1187.       BEGIN;
  1188.  
  1189.         DEC(loop_count);
  1190.  
  1191.         dump_action_item(p);
  1192.         p := p^.next_action;
  1193.  
  1194.       END;
  1195.  
  1196.     close_dump;
  1197.  
  1198.   END;
  1199.  
  1200. (*===========================================================================*)
  1201. (* Dump a search block                                                       *)
  1202. (*===========================================================================*)
  1203.  
  1204. PROCEDURE dump_search_item(p : search_block_ptr);
  1205.   BEGIN;
  1206.  
  1207.     WRITELN(dump_file, 'Dumping search item at -- ', p2x(p));
  1208.     WRITELN(dump_file);
  1209.  
  1210.     WRITELN(dump_file, 'Next search  = ', p2x(p^.search_next));
  1211.     WRITELN(dump_file, 'Direction    = ', p^.search_direction);
  1212.     WRITELN(dump_file, 'Ascend       = ', p^.search_ascend   );
  1213.     WRITELN(dump_file, 'Above        = ', p^.search_above    );
  1214.     WRITELN(dump_file, 'No Kill      = ', p^.search_nok      );
  1215.     WRITELN(dump_file, 'Invert       = ', p^.search_invert   );
  1216.     WRITELN(dump_file, 'One only     = ', p^.search_one_only );
  1217.     WRITELN(dump_file, 'Type         = ', p^.search_type     );
  1218.     WRITELN(dump_file, 'Last msg     = ', p2x(p^.search_last));
  1219.     WRITELN(dump_file, 'Message flag = ', w2x(p^.search_mf)  );
  1220.     WRITELN(dump_file, 'Msg number   = ', p^.search_msg_no   );
  1221.     WRITELN(dump_file, 'Data         = ');
  1222.     hex_dump(@p^.search_dt, 32);
  1223.  
  1224.   END;
  1225.  
  1226. (*===========================================================================*)
  1227. (* Dump all search blocks in a chain                                         *)
  1228. (*===========================================================================*)
  1229.  
  1230. PROCEDURE dump_search_chain(p : search_block_ptr);
  1231.  
  1232.   VAR
  1233.     loop_count : BYTE;
  1234.  
  1235.   BEGIN;
  1236.  
  1237.     open_dump;
  1238.     loop_count := 10;
  1239.  
  1240.     WRITELN(dump_file, 'Dumping search chain starting at -- ', p2x(p));
  1241.     WRITELN(dump_file);
  1242.  
  1243.     WHILE (p <> NIL) AND (loop_count > 0) DO
  1244.       BEGIN;
  1245.         DEC(loop_count);
  1246.         dump_search_item(p);
  1247.         p := p^.search_next;
  1248.       END;
  1249.  
  1250.     close_dump;
  1251.  
  1252.   END;
  1253.  
  1254. END.
  1255.